home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / cpp / part02 < prev    next >
Encoding:
Internet Message Format  |  1990-01-18  |  47.1 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i023: cpp - a c preprocessor with some ANSI features, Part02/05
  5. Message-ID: <11031@xanth.cs.odu.edu>
  6. Date: 18 Jan 90 00:18:29 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  9. Lines: 1503
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11.  
  12. Submitted-by: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  13. Posting-number: Volume 90, Issue 023
  14. Archive-name: unix/cpp/part02
  15.  
  16. #!/bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 2 (of 5)."
  23. # Contents:  Cpp2.c Cpp3.c org/cpp.mem
  24. # Wrapped by tadguy@xanth on Wed Jan 17 19:17:33 1990
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'Cpp2.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'Cpp2.c'\"
  28. else
  29. echo shar: Extracting \"'Cpp2.c'\" \(17735 characters\)
  30. sed "s/^X//" >'Cpp2.c' <<'END_OF_FILE'
  31. X/*
  32. X *                C P P 2 . C
  33. X *
  34. X *               Process #control lines
  35. X *
  36. X * Edit history
  37. X * 13-Nov-84    MM    Split from cpp1.c
  38. X * 21-Oct-85    RMS    Do not turn on `instring' while reading #include arg.
  39. X *            Rename `token' to `tokenbuf'.
  40. X *            Flush tabs at end of #include line, like spaces.
  41. X * 14-Mar-86    FNF    Incorporate macro based C debugging package.
  42. X *            Port to Commodore AMIGA.
  43. X * 25-May-86    FNF    Change handling of fully qualified include file
  44. X *            pathnames (like "/usr/include/stdio.h" for unix,
  45. X *            or "df0:include/stdio.h" for the Amiga) to be
  46. X *            used verbatum in the first open attempt.
  47. X * 20-Aug-88    Ois    Added #error. Passed unrecognized # commands.
  48. X *            Added \n when those lines are passed.
  49. X */
  50. X
  51. X#include    <stdio.h>
  52. X#include    <ctype.h>
  53. X#include    "cppdef.h"
  54. X#include    "cpp.h"
  55. X#if HOST == SYS_VMS
  56. X/*
  57. X * Include the rms stuff.  (We can't just include rms.h as it uses the
  58. X * VaxC-specific library include syntax that Decus CPP doesn't support.
  59. X * By including things by hand, we can CPP ourself.)
  60. X */
  61. X#include    <nam.h>
  62. X#include    <fab.h>
  63. X#include    <rab.h>
  64. X#include    <rmsdef.h>
  65. X#endif
  66. X
  67. X/*
  68. X * Generate (by hand-inspection) a set of unique values for each control
  69. X * operator.  Note that this is not guaranteed to work for non-Ascii
  70. X * machines.  CPP won't compile if there are hash conflicts.
  71. X */
  72. X
  73. X#define L_assert    ('a' + ('s' << 1))
  74. X#define L_define    ('d' + ('f' << 1))
  75. X#define L_elif        ('e' + ('i' << 1))
  76. X#define L_else        ('e' + ('s' << 1))
  77. X#define L_endif     ('e' + ('d' << 1))
  78. X#define L_error     ('e' + ('r' << 1))
  79. X#define L_if        ('i' + (EOS << 1))
  80. X#define L_ifdef     ('i' + ('d' << 1))
  81. X#define L_ifndef    ('i' + ('n' << 1))
  82. X#define L_include    ('i' + ('c' << 1))
  83. X#define L_line        ('l' + ('n' << 1))
  84. X#define L_nogood    (EOS + (EOS << 1))      /* To catch #i          */
  85. X#define L_pragma    ('p' + ('a' << 1))
  86. X#define L_undef     ('u' + ('d' << 1))
  87. X#if DEBUG
  88. X#define L_debug     ('d' + ('b' << 1))      /* #debug               */
  89. X#define L_nodebug    ('n' + ('d' << 1))      /* #nodebug             */
  90. X#endif
  91. X
  92. Xint
  93. Xcontrol(counter)
  94. Xint        counter;    /* Pending newline counter        */
  95. X/*
  96. X * Process #control lines.  Simple commands are processed inline,
  97. X * while complex commands have their own subroutines.
  98. X *
  99. X * The counter is used to force out a newline before #line, and
  100. X * #pragma commands.  This prevents these commands from ending up at
  101. X * the end of the previous line if cpp is invoked with the -C option.
  102. X */
  103. X{
  104. X    register int        c;
  105. X    register char        *tp;
  106. X    register int        hash;
  107. X    char            *ep;
  108. X
  109. X    DBUG_ENTER ("control");
  110. X    c = skipws();
  111. X    if (c == '\n' || c == EOF_CHAR)
  112. X        DBUG_RETURN (counter + 1);
  113. X    if (!isdigit(c))
  114. X        scanid(c);                  /* Get #word to tokenbuf        */
  115. X    else {
  116. X        unget();                    /* Hack -- allow #123 as a      */
  117. X        strcpy(tokenbuf, "line");   /* synonym for #line 123        */
  118. X    }
  119. X    hash = (tokenbuf[1] == EOS) ? L_nogood : (tokenbuf[0] + (tokenbuf[2] << 1));
  120. X    switch (hash) {
  121. X    case L_assert:    tp = "assert";          break;
  122. X    case L_define:    tp = "define";          break;
  123. X    case L_elif:    tp = "elif";            break;
  124. X    case L_else:    tp = "else";            break;
  125. X    case L_endif:    tp = "endif";           break;
  126. X    case L_error:    tp = "error";           break;
  127. X    case L_if:    tp = "if";              break;
  128. X    case L_ifdef:    tp = "ifdef";           break;
  129. X    case L_ifndef:    tp = "ifndef";          break;
  130. X    case L_include: tp = "include";         break;
  131. X    case L_line:    tp = "line";            break;
  132. X    case L_pragma:    tp = "pragma";          break;
  133. X    case L_undef:    tp = "undef";           break;
  134. X#if DEBUG
  135. X    case L_debug:    tp = "debug";           break;
  136. X    case L_nodebug: tp = "nodebug";         break;
  137. X#endif
  138. X    default:    hash = L_nogood;
  139. X    case L_nogood:    tp = "";                break;
  140. X    }
  141. X    if (!streq(tp, tokenbuf))
  142. X        hash = L_nogood;
  143. X    /*
  144. X     * hash is set to a unique value corresponding to the
  145. X     * control keyword (or L_nogood if we think it's nonsense).
  146. X     */
  147. X    if (infile->fp == NULL)
  148. X        cwarn("Control line \"%s\" within macro expansion", tokenbuf);
  149. X    if (!compiling) {                       /* Not compiling now    */
  150. X        switch (hash) {
  151. X        case L_if:                /* These can't turn     */
  152. X        case L_ifdef:            /*  compilation on, but */
  153. X        case L_ifndef:            /*   we must nest #if's */
  154. X        if (++ifptr >= &ifstack[BLK_NEST])
  155. X            goto if_nest_err;
  156. X        *ifptr = 0;            /* !WAS_COMPILING    */
  157. X        case L_line:            /* Many         */
  158. X        /*
  159. X         * Are pragma's always processed?
  160. X         */
  161. X        case L_pragma:            /*  options        */
  162. X        case L_include:            /*   are uninteresting    */
  163. X        case L_define:            /*    if we        */
  164. X        case L_undef:            /*     aren't           */
  165. X        case L_assert:            /*    compiling.    */
  166. X        case L_error:
  167. Xdump_line:    skipnl();                       /* Ignore rest of line  */
  168. X        DBUG_RETURN (counter + 1);
  169. X        }
  170. X    }
  171. X    /*
  172. X     * Make sure that #line and #pragma are output on a fresh line.
  173. X     */
  174. X    if (counter > 0 && (hash == L_line || hash == L_pragma)) {
  175. X        putchar('\n');
  176. X        counter--;
  177. X    }
  178. X    switch (hash) {
  179. X    case L_line:
  180. X        /*
  181. X         * Parse the line to update the line number and "progname"
  182. X         * field and line number for the next input line.
  183. X         * Set wrongline to force it out later.
  184. X         */
  185. X        c = skipws();
  186. X        workp = work;            /* Save name in work    */
  187. X        while (c != '\n' && c != EOF_CHAR) {
  188. X        save(c);
  189. X        c = get();
  190. X        }
  191. X        unget();
  192. X        save(EOS);
  193. X        /*
  194. X         * Split #line argument into <line-number> and <name>
  195. X         * We subtract 1 as we want the number of the next line.
  196. X         */
  197. X        line = atoi(work) - 1;              /* Reset line number    */
  198. X        for (tp = work; isdigit(*tp) || type[*tp] == SPA; tp++)
  199. X        ;                /* Skip over digits    */
  200. X        if (*tp != EOS) {                   /* Got a filename, so:  */
  201. X        if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) {
  202. X            tp++;            /* Skip over left quote */
  203. X            *ep = EOS;            /* And ignore right one */
  204. X        }
  205. X        if (infile->progname != NULL)   /* Give up the old name */
  206. X            free(infile->progname);     /* if it's allocated.   */
  207. X        infile->progname = savestring(tp);
  208. X        }
  209. X        wrongline = TRUE;            /* Force output later    */
  210. X        break;
  211. X
  212. X    case L_include:
  213. X        doinclude();
  214. X        break;
  215. X
  216. X    case L_define:
  217. X        dodefine();
  218. X        break;
  219. X
  220. X    case L_undef:
  221. X        doundef();
  222. X        break;
  223. X
  224. X    case L_else:
  225. X        if (ifptr == &ifstack[0])
  226. X        goto nest_err;
  227. X        else if ((*ifptr & ELSE_SEEN) != 0)
  228. X        goto else_seen_err;
  229. X        *ifptr |= ELSE_SEEN;
  230. X        if ((*ifptr & WAS_COMPILING) != 0) {
  231. X        if (compiling || (*ifptr & TRUE_SEEN) != 0)
  232. X            compiling = FALSE;
  233. X        else {
  234. X            compiling = TRUE;
  235. X        }
  236. X        }
  237. X        break;
  238. X
  239. X    case L_elif:
  240. X        if (ifptr == &ifstack[0])
  241. X        goto nest_err;
  242. X        else if ((*ifptr & ELSE_SEEN) != 0) {
  243. Xelse_seen_err:    cerror("#%s may not follow #else", tokenbuf);
  244. X        goto dump_line;
  245. X        }
  246. X        if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) {
  247. X        compiling = FALSE;        /* Done compiling stuff */
  248. X        goto dump_line;         /* Skip this clause    */
  249. X        }
  250. X        doif(L_if);
  251. X        break;
  252. X
  253. X    case L_error:
  254. X        cerror("#error directive encountered", NULLST);
  255. X        break;
  256. X
  257. X    case L_if:
  258. X    case L_ifdef:
  259. X    case L_ifndef:
  260. X        if (++ifptr >= &ifstack[BLK_NEST])
  261. Xif_nest_err:    cfatal("Too many nested #%s statements", tokenbuf);
  262. X        *ifptr = WAS_COMPILING;
  263. X        doif(hash);
  264. X        break;
  265. X
  266. X    case L_endif:
  267. X        if (ifptr == &ifstack[0]) {
  268. Xnest_err:    cerror("#%s must be in an #if", tokenbuf);
  269. X        goto dump_line;
  270. X        }
  271. X        if (!compiling && (*ifptr & WAS_COMPILING) != 0)
  272. X        wrongline = TRUE;
  273. X        compiling = ((*ifptr & WAS_COMPILING) != 0);
  274. X        --ifptr;
  275. X        break;
  276. X
  277. X    case L_assert:
  278. X        if (eval() == 0)
  279. X        cerror("Preprocessor assertion failure", NULLST);
  280. X        break;
  281. X
  282. X    case L_pragma:
  283. X        /*
  284. X         * #pragma is provided to pass "options" to later
  285. X         * passes of the compiler.    cpp doesn't have any yet.
  286. X         */
  287. X        printf("#pragma ");
  288. Xpass_line:
  289. X        while ((c = get()) != '\n' && c != EOF_CHAR)
  290. X        cput(c);
  291. X        unget();
  292. X        cput('\n');
  293. X        break;
  294. X
  295. X#if DEBUG
  296. X    case L_debug:
  297. X        if (debug == 0)
  298. X        dumpdef("debug set on");
  299. X        debug++;
  300. X        break;
  301. X
  302. X    case L_nodebug:
  303. X        debug--;
  304. X        break;
  305. X#endif
  306. X
  307. X    default:
  308. X        /*
  309. X         * Undefined #control keyword.
  310. X         * Note: the correct behavior may be to warn and
  311. X         * pass the line to a subsequent compiler pass.
  312. X         * This would allow #asm or similar extensions.
  313. X         */
  314. X        /* cerror("Illegal # command \"%s\"", tokenbuf); */
  315. X        printf("#%s ", tokenbuf);
  316. X        goto pass_line;
  317. X        break;
  318. X    }
  319. X    if (hash != L_include) {
  320. X#if OLD_PREPROCESSOR
  321. X        /*
  322. X         * Ignore the rest of the #control line so you can write
  323. X         *        #if    foo
  324. X         *        #endif    foo
  325. X         */
  326. X        goto dump_line;            /* Take common exit    */
  327. X#else
  328. X        if (skipws() != '\n') {
  329. X        cwarn("Unexpected text in #control line ignored", NULLST);
  330. X        skipnl();
  331. X        }
  332. X#endif
  333. X    }
  334. X    DBUG_RETURN (counter + 1);
  335. X}
  336. X
  337. XFILE_LOCAL
  338. Xdoif(hash)
  339. Xint        hash;
  340. X/*
  341. X * Process an #if, #ifdef, or #ifndef.    The latter two are straightforward,
  342. X * while #if needs a subroutine of its own to evaluate the expression.
  343. X *
  344. X * doif() is called only if compiling is TRUE.  If false, compilation
  345. X * is always supressed, so we don't need to evaluate anything.  This
  346. X * supresses unnecessary warnings.
  347. X */
  348. X{
  349. X    register int        c;
  350. X    register int        found;
  351. X
  352. X    DBUG_ENTER ("doif");
  353. X    if ((c = skipws()) == '\n' || c == EOF_CHAR) {
  354. X        unget();
  355. X        goto badif;
  356. X    }
  357. X    if (hash == L_if) {
  358. X        unget();
  359. X        found = (eval() != 0);      /* Evaluate expr, != 0 is  TRUE */
  360. X        hash = L_ifdef;        /* #if is now like #ifdef    */
  361. X    }
  362. X    else {
  363. X        if (type[c] != LET)         /* Next non-blank isn't letter  */
  364. X        goto badif;        /* ... is an error        */
  365. X        found = (lookid(c) != NULL); /* Look for it in symbol table */
  366. X    }
  367. X    if (found == (hash == L_ifdef)) {
  368. X        compiling = TRUE;
  369. X        *ifptr |= TRUE_SEEN;
  370. X    }
  371. X    else {
  372. X        compiling = FALSE;
  373. X    }
  374. X    DBUG_VOID_RETURN;
  375. X
  376. Xbadif:    cerror("#if, #ifdef, or #ifndef without an argument", NULLST);
  377. X#if !OLD_PREPROCESSOR
  378. X    skipnl();                               /* Prevent an extra     */
  379. X    unget();                                /* Error message        */
  380. X#endif
  381. X    DBUG_VOID_RETURN;
  382. X}
  383. X
  384. XFILE_LOCAL
  385. Xdoinclude()
  386. X/*
  387. X * Process the #include control line.
  388. X * There are three variations:
  389. X *    #include "file"         search somewhere relative to the
  390. X *                current source file, if not found,
  391. X *                treat as #include <file>.
  392. X *    #include <file>     Search in an implementation-dependent
  393. X *                list of places.
  394. X *    #include token        Expand the token, it must be one of
  395. X *                "file" or <file>, process as such.
  396. X *
  397. X * Note: the November 12 draft forbids '>' in the #include <file> format.
  398. X * This restriction is unnecessary and not implemented.
  399. X */
  400. X{
  401. X    register int        c;
  402. X    register int        delim;
  403. X#if HOST == SYS_VMS
  404. X    char            def_filename[NAM$C_MAXRSS + 1];
  405. X#endif
  406. X
  407. X    DBUG_ENTER ("doinclude");
  408. X    delim = macroid(skipws());
  409. X    if (delim != '<' && delim != '"')
  410. X        goto incerr;
  411. X    if (delim == '<')
  412. X        delim = '>';
  413. X    workp = work;
  414. X    while ((c = get()) != '\n' && c != EOF_CHAR)
  415. X        save(c);                    /* Put it away.                 */
  416. X    unget();                        /* Force nl after includee      */
  417. X    /*
  418. X     * The draft is unclear if the following should be done.
  419. X     */
  420. X    while (--workp >= work && (*workp == ' ' || *workp == '\t'))
  421. X        ;                /* Trim blanks from filename    */
  422. X    if (*workp != delim)
  423. X        goto incerr;
  424. X    *workp = EOS;            /* Terminate filename        */
  425. X#if HOST == SYS_VMS
  426. X    /*
  427. X     * Assume the default .h filetype.
  428. X     */
  429. X    if (!vmsparse(work, ".H", def_filename)) {
  430. X        perror(work);               /* Oops.                        */
  431. X        goto incerr;
  432. X    }
  433. X    else if (openinclude(def_filename, (delim == '"')))
  434. X        DBUG_VOID_RETURN;
  435. X#else
  436. X    if (openinclude(work, (delim == '"')))
  437. X        DBUG_VOID_RETURN;
  438. X#endif
  439. X    /*
  440. X     * No sense continuing if #include file isn't there.
  441. X     */
  442. X    cfatal("Cannot open include file \"%s\"", work);
  443. X
  444. Xincerr: cerror("#include syntax error", NULLST);
  445. X    DBUG_VOID_RETURN;
  446. X}
  447. X
  448. XFILE_LOCAL int
  449. Xopeninclude(filename, searchlocal)
  450. Xchar        *filename;        /* Input file name        */
  451. Xint        searchlocal;        /* TRUE if #include "file"      */
  452. X/*
  453. X * Actually open an include file.  This routine is only called from
  454. X * doinclude() above, but was written as a separate subroutine for
  455. X * programmer convenience.  It searches the list of directories
  456. X * and actually opens the file, linking it into the list of
  457. X * active files.  Returns TRUE if the file was opened, FALSE
  458. X * if openinclude() fails.  No error message is printed.
  459. X */
  460. X{
  461. X    register char        **incptr;
  462. X#if HOST == SYS_VMS
  463. X#if NWORK < (NAM$C_MAXRSS + 1)
  464. X    << error, NWORK isn't greater than NAM$C_MAXRSS >>
  465. X#endif
  466. X#endif
  467. X    char            tmpname[NWORK]; /* Filename work area    */
  468. X
  469. X    DBUG_ENTER ("openinclude");
  470. X#if HOST == SYS_UNIX
  471. X    if ((filename[0] == '/') && openfile(filename)) {
  472. X        DBUG_RETURN (TRUE);
  473. X    }
  474. X#endif
  475. X#if HOST == SYS_AMIGADOS
  476. X    if ((strchr (filename, ':') != NULL) && openfile (filename)) {
  477. X        DBUG_RETURN (TRUE);
  478. X    }
  479. X#endif
  480. X    if (searchlocal) {
  481. X        /*
  482. X         * Look in local directory first.
  483. X         * Try to open filename relative to the directory of the current
  484. X         * source file (as opposed to the current directory). (ARF, SCK).
  485. X         * Note that the fully qualified pathname is always built by
  486. X         * discarding the last pathname component of the source file
  487. X         * name then tacking on the #include argument.
  488. X         */
  489. X        if(hasdirectory(infile->filename, tmpname)) {
  490. X        strcat(tmpname, filename);
  491. X        } else {
  492. X        strcpy(tmpname, filename);
  493. X        }
  494. X        if (openfile(tmpname))
  495. X        DBUG_RETURN (TRUE);
  496. X    }
  497. X    /*
  498. X     * Look in any directories specified by -I command line
  499. X     * arguments, then in the builtin search list.
  500. X     */
  501. X    for (incptr = incdir; incptr < incend; incptr++) {
  502. X        if (strlen(*incptr) + strlen(filename) >= sizeof(tmpname)) {
  503. X        cfatal("Filename work buffer overflow", NULLST);
  504. X        } else {
  505. X#if HOST == SYS_UNIX                /* Implied '/' */
  506. X        sprintf(tmpname, "%s/%s", *incptr, filename);
  507. X#else
  508. X        sprintf(tmpname, "%s%s", *incptr, filename);
  509. X#endif
  510. X        if (openfile(tmpname))
  511. X            DBUG_RETURN (TRUE);
  512. X        }
  513. X    }
  514. X    DBUG_RETURN (FALSE);
  515. X}
  516. X
  517. XFILE_LOCAL int
  518. Xhasdirectory(source, result)
  519. Xchar        *source;    /* Directory to examine         */
  520. Xchar        *result;    /* Put directory stuff here        */
  521. X/*
  522. X * If a device or directory is found in the source filename string, the
  523. X * node/device/directory part of the string is copied to result and
  524. X * hasdirectory returns TRUE.  Else, nothing is copied and it returns FALSE.
  525. X */
  526. X{
  527. X#if HOST == SYS_UNIX
  528. X    register char        *tp;
  529. X
  530. X    DBUG_ENTER ("hasdirectory");
  531. X    if ((tp = strrchr(source, '/')) == NULL)
  532. X        DBUG_RETURN (FALSE);
  533. X    else {
  534. X        strncpy(result, source, tp - source + 1);
  535. X        result[tp - source + 1] = EOS;
  536. X        DBUG_RETURN (TRUE);
  537. X    }
  538. X#elif HOST == SYS_AMIGADOS
  539. X    register char        *tp1, *tp2;
  540. X
  541. X    DBUG_ENTER ("hasdirectory");
  542. X
  543. X    if ((tp1 = strrchr(source, ':')) == NULL)
  544. X        tp1 = source;
  545. X    if ((tp2 = strrchr(tp1, '/')) == NULL)
  546. X        tp2 = tp1;
  547. X
  548. X    if (tp2 == source)
  549. X        DBUG_RETURN (FALSE);
  550. X    else {
  551. X        strncpy(result, source, tp2 - source + 1);
  552. X        result[tp2 - source + 1] = EOS;
  553. X        DBUG_RETURN (TRUE);
  554. X    }
  555. X#elif HOST == SYS_VMS
  556. X    DBUG_ENTER ("hasdirectory");
  557. X    if (vmsparse(source, NULLST, result)
  558. X     && result[0] != EOS)
  559. X        DBUG_RETURN (TRUE);
  560. X    else {
  561. X        DBUG_RETURN (FALSE);
  562. X    }
  563. X#else
  564. X    /*
  565. X     * Random DEC operating system (RSX, RT11, RSTS/E)
  566. X     */
  567. X    register char        *tp;
  568. X
  569. X        DBUG_ENTER ("hasdirectory");
  570. X    if ((tp = strrchr(source, ']')) == NULL
  571. X     && (tp = strrchr(source, ':')) == NULL)
  572. X        DBUG_RETURN (FALSE);
  573. X    else {
  574. X        strncpy(result, source, tp - source + 1);
  575. X        result[tp - source + 1] = EOS;
  576. X        DBUG_RETURN (TRUE);
  577. X    }
  578. X#endif
  579. X}
  580. X
  581. X#if HOST == SYS_VMS
  582. X
  583. X/*
  584. X * EXP_DEV is set if a device was specified, EXP_DIR if a directory
  585. X * is specified.  (Both set indicate a file-logical, but EXP_DEV
  586. X * would be set by itself if you are reading, say, SYS$INPUT:)
  587. X */
  588. X#define DEVDIR (NAM$M_EXP_DEV | NAM$M_EXP_DIR)
  589. X
  590. XFILE_LOCAL int
  591. Xvmsparse(source, defstring, result)
  592. Xchar        *source;
  593. Xchar        *defstring;    /* non-NULL -> default string.        */
  594. Xchar        *result;    /* Size is at least NAM$C_MAXRSS + 1    */
  595. X/*
  596. X * Parse the source string, applying the default (properly, using
  597. X * the system parse routine), storing it in result.
  598. X * TRUE if it parsed, FALSE on error.
  599. X *
  600. X * If defstring is NULL, there are no defaults and result gets
  601. X * (just) the node::[directory] part of the string (possibly "")
  602. X */
  603. X{
  604. X    struct FAB    fab = cc$rms_fab;    /* File access block    */
  605. X    struct NAM    nam = cc$rms_nam;    /* File name block    */
  606. X    char        fullname[NAM$C_MAXRSS + 1];
  607. X    register char    *rp;            /* Result pointer    */
  608. X
  609. X    DBUG_ENTER ("vmsparse");
  610. X    fab.fab$l_nam = &nam;            /* fab -> nam        */
  611. X    fab.fab$l_fna = source;         /* Source filename    */
  612. X    fab.fab$b_fns = strlen(source);         /* Size of source       */
  613. X    fab.fab$l_dna = defstring;        /* Default string    */
  614. X    if (defstring != NULLST)
  615. X        fab.fab$b_dns = strlen(defstring);  /* Size of default      */
  616. X    nam.nam$l_esa = fullname;        /* Expanded filename    */
  617. X    nam.nam$b_ess = NAM$C_MAXRSS;        /* Expanded name size    */
  618. X    if (sys$parse(&fab) == RMS$_NORMAL) {   /* Parse away           */
  619. X        fullname[nam.nam$b_esl] = EOS;    /* Terminate string    */
  620. X        result[0] = EOS;            /* Just in case     */
  621. X        rp = &result[0];
  622. X        /*
  623. X         * Remove stuff added implicitly, accepting node names and
  624. X         * dev:[directory] strings (but not process-permanent files).
  625. X         */
  626. X        if ((nam.nam$l_fnb & NAM$M_PPF) == 0) {
  627. X        if ((nam.nam$l_fnb & NAM$M_NODE) != 0) {
  628. X            strncpy(result, nam.nam$l_node, nam.nam$b_node);
  629. X            rp += nam.nam$b_node;
  630. X            *rp = EOS;
  631. X        }
  632. X        if ((nam.nam$l_fnb & DEVDIR) == DEVDIR) {
  633. X            strncpy(rp, nam.nam$l_dev, nam.nam$b_dev + nam.nam$b_dir);
  634. X            rp += nam.nam$b_dev + nam.nam$b_dir;
  635. X            *rp = EOS;
  636. X        }
  637. X        }
  638. X        if (defstring != NULLST) {
  639. X        strncpy(rp, nam.nam$l_name, nam.nam$b_name + nam.nam$b_type);
  640. X        rp += nam.nam$b_name + nam.nam$b_type;
  641. X        *rp = EOS;
  642. X        if ((nam.nam$l_fnb & NAM$M_EXP_VER) != 0) {
  643. X            strncpy(rp, nam.nam$l_ver, nam.nam$b_ver);
  644. X            rp[nam.nam$b_ver] = EOS;
  645. X        }
  646. X        }
  647. X        DBUG_RETURN (TRUE);
  648. X    }
  649. X    DBUG_RETURN (FALSE);
  650. X}
  651. X#endif
  652. X
  653. END_OF_FILE
  654. if test 17735 -ne `wc -c <'Cpp2.c'`; then
  655.     echo shar: \"'Cpp2.c'\" unpacked with wrong size!
  656. fi
  657. # end of 'Cpp2.c'
  658. fi
  659. if test -f 'Cpp3.c' -a "${1}" != "-c" ; then 
  660.   echo shar: Will not clobber existing file \"'Cpp3.c'\"
  661. else
  662. echo shar: Extracting \"'Cpp3.c'\" \(14103 characters\)
  663. sed "s/^X//" >'Cpp3.c' <<'END_OF_FILE'
  664. X/*
  665. X *                C P P 3 . C
  666. X *
  667. X *            File open and command line options
  668. X *
  669. X * Edit history
  670. X * 13-Nov-84    MM    Split from cpp1.c
  671. X * 21-Oct-85    rms    Make -g command arg not cause an error.
  672. X * 14-Mar-86    FNF    Incorporate macro based C debugging package.
  673. X *            Port to the Commodore AMIGA.
  674. X * 20-Aug-88    Ois    Added __TIME__, and changed __DATE__ to standard.
  675. X */
  676. X
  677. X#include    <stdio.h>
  678. X#include    <ctype.h>
  679. X#include    <time.h>    /*OIS*0.92*/
  680. X#include    "cppdef.h"
  681. X#include    "cpp.h"
  682. X#if DEBUG && (HOST == SYS_VMS || HOST == SYS_UNIX)
  683. X#include    <signal.h>
  684. Xextern int    abort();                /* For debugging                */
  685. X#endif
  686. X
  687. Xint
  688. Xopenfile(filename)
  689. Xchar        *filename;
  690. X/*
  691. X * Open a file, add it to the linked list of open files.
  692. X * This is called only from openfile() above.
  693. X */
  694. X{
  695. X    register FILE        *fp;
  696. X    extern FILE        *fopen ();
  697. X
  698. X    DBUG_ENTER ("openfile");
  699. X    if ((fp = fopen(filename, "r")) == NULL) {
  700. X#if DEBUG
  701. X        perror(filename);
  702. X#endif
  703. X        DBUG_RETURN (FALSE);
  704. X    }
  705. X#if DEBUG
  706. X    if (debug)
  707. X        fprintf(stderr, "Reading from \"%s\"\n", filename);
  708. X#endif
  709. X    addfile(fp, filename);
  710. X    DBUG_RETURN (TRUE);
  711. X}
  712. X
  713. Xaddfile(fp, filename)
  714. XFILE        *fp;            /* Open file pointer        */
  715. Xchar        *filename;        /* Name of the file        */
  716. X/*
  717. X * Initialize tables for this open file.  This is called from openfile()
  718. X * above (for #include files), and from the entry to cpp to open the main
  719. X * input file.    It calls a common routine, getfile() to build the FILEINFO
  720. X * structure which is used to read characters.    (getfile() is also called
  721. X * to setup a macro replacement.)
  722. X */
  723. X{
  724. X    register FILEINFO    *file;
  725. X    extern FILEINFO     *getfile();
  726. X
  727. X    DBUG_ENTER ("addfile");
  728. X    file = getfile(NBUFF, filename);
  729. X    file->fp = fp;            /* Better remember FILE *    */
  730. X    file->buffer[0] = EOS;        /* Initialize for first read    */
  731. X    line = 1;            /* Working on line 1 now    */
  732. X    wrongline = TRUE;        /* Force out initial #line    */
  733. X    DBUG_VOID_RETURN;
  734. X}
  735. X
  736. Xsetincdirs()
  737. X/*
  738. X * Append system-specific directories to the include directory list.
  739. X * Called only when cpp is started.
  740. X */
  741. X{
  742. X
  743. X    DBUG_ENTER ("setincdirs");
  744. X#ifdef    CPP_INCLUDE
  745. X    *incend++ = CPP_INCLUDE;
  746. X#define IS_INCLUDE    1
  747. X#else
  748. X#define IS_INCLUDE    0
  749. X#endif
  750. X
  751. X#if HOST == SYS_UNIX
  752. X    *incend++ = "/usr/include";
  753. X#define MAXINCLUDE    (NINCLUDE - 1 - IS_INCLUDE)
  754. X#endif
  755. X
  756. X#if HOST == SYS_AMIGADOS
  757. X    *incend++ = "df0:include/";      /* These should be fixed. fnf */
  758. X    *incend++ = "df1:include/";
  759. X#define MAXINCLUDE    (NINCLUDE - 2 - IS_INCLUDE)
  760. X#endif
  761. X
  762. X#if HOST == SYS_VMS
  763. X    extern char    *getenv();
  764. X
  765. X    if (getenv("C$LIBRARY") != NULL)
  766. X        *incend++ = "C$LIBRARY:";
  767. X    *incend++ = "SYS$LIBRARY:";
  768. X#define MAXINCLUDE    (NINCLUDE - 2 - IS_INCLUDE)
  769. X#endif
  770. X
  771. X#if HOST == SYS_RSX
  772. X    extern int    $$rsts;         /* TRUE on RSTS/E    */
  773. X    extern int    $$pos;            /* TRUE on PRO-350 P/OS */
  774. X    extern int    $$vms;            /* TRUE on VMS compat.    */
  775. X
  776. X    if ($$pos) {                            /* P/OS?                */
  777. X        *incend++ = "SY:[ZZDECUSC]";        /* C #includes          */
  778. X        *incend++ = "LB:[1,5]";             /* RSX library          */
  779. X    }
  780. X    else if ($$rsts) {                      /* RSTS/E?              */
  781. X        *incend++ = "SY:@";                 /* User-defined account */
  782. X        *incend++ = "C:";                   /* Decus-C library      */
  783. X        *incend++ = "LB:[1,1]";             /* RSX library          */
  784. X    }
  785. X    else if ($$vms) {                       /* VMS compatibility?   */
  786. X        *incend++ = "C:";
  787. X    }
  788. X    else {                    /* Plain old RSX/IAS    */
  789. X        *incend++ = "LB:[1,1]";
  790. X    }
  791. X#define MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  792. X#endif
  793. X
  794. X#if HOST == SYS_RT11
  795. X    extern int    $$rsts;         /* RSTS/E emulation?    */
  796. X
  797. X    if ($$rsts)
  798. X        *incend++ = "SY:@";                 /* User-defined account */
  799. X    *incend++ = "C:";                       /* Decus-C library disk */
  800. X    *incend++ = "SY:";                      /* System (boot) disk   */
  801. X#define MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  802. X#endif
  803. X    DBUG_VOID_RETURN;
  804. X}
  805. X
  806. Xint
  807. Xdooptions(argc, argv)
  808. Xint        argc;
  809. Xchar        *argv[];
  810. X/*
  811. X * dooptions is called to process command line arguments (-Detc).
  812. X * It is called only at cpp startup.
  813. X */
  814. X{
  815. X    register char        *ap;
  816. X    register DEFBUF     *dp;
  817. X    register int        c;
  818. X    int            i, j;
  819. X    char            *arg;
  820. X    SIZES            *sizp;        /* For -S        */
  821. X    int            size;        /* For -S        */
  822. X    int            isdatum;    /* FALSE for -S*    */
  823. X    int            endtest;    /* For -S        */
  824. X
  825. X    DBUG_ENTER ("dooptions");
  826. X    for (i = j = 1; i < argc; i++) {
  827. X        arg = ap = argv[i];
  828. X        if (*ap++ != '-' || *ap == EOS)
  829. X        argv[j++] = argv[i];
  830. X        else {
  831. X        c = *ap++;            /* Option byte        */
  832. X        if (islower(c))                 /* Normalize case       */
  833. X            c = toupper(c);
  834. X        switch (c) {                    /* Command character    */
  835. X        case 'C':                       /* Keep comments        */
  836. X            cflag = TRUE;
  837. X            keepcomments = TRUE;
  838. X            break;
  839. X
  840. X        case 'D':                       /* Define symbol        */
  841. X#if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
  842. X            zap_uc(ap);                 /* Force define to U.C. */
  843. X#endif
  844. X            /*
  845. X             * If the option is just "-Dfoo", make it -Dfoo=1
  846. X             */
  847. X            while (*ap != EOS && *ap != '=')
  848. X            ap++;
  849. X            if (*ap == EOS)
  850. X            ap = "1";
  851. X            else
  852. X            *ap++ = EOS;
  853. X            /*
  854. X             * Now, save the word and its definition.
  855. X             */
  856. X            dp = defendel(argv[i] + 2, FALSE);
  857. X            dp->repl = savestring(ap);
  858. X            dp->nargs = DEF_NOARGS;
  859. X            break;
  860. X
  861. X        case 'E':                       /* Ignore non-fatal     */
  862. X            eflag = TRUE;        /* errors.        */
  863. X            break;
  864. X
  865. X        case 'G':                       /* Cmpiler's debug switch */
  866. X            break;
  867. X
  868. X        case 'I':                       /* Include directory    */
  869. X            if (incend >= &incdir[MAXINCLUDE])
  870. X            cfatal("Too many include directories", NULLST);
  871. X            *incend++ = ap;
  872. X            break;
  873. X
  874. X        case 'N':                       /* No predefineds       */
  875. X            nflag++;            /* Repeat to undefine    */
  876. X            break;            /* __LINE__, etc.    */
  877. X
  878. X#if OK_SIZEOF
  879. X        case 'S':
  880. X            sizp = size_table;
  881. X            if (isdatum = (*ap != '*')) /* If it's just -S,     */
  882. X            endtest = T_FPTR;    /* Stop here        */
  883. X            else {            /* But if it's -S*      */
  884. X            ap++;            /* Step over '*'        */
  885. X            endtest = 0;        /* Stop at end marker    */
  886. X            }
  887. X            while (sizp->bits != endtest && *ap != EOS) {
  888. X            if (!isdigit(*ap)) {    /* Skip to next digit   */
  889. X                ap++;
  890. X                continue;
  891. X            }
  892. X            size = 0;        /* Compile the value    */
  893. X            while (isdigit(*ap)) {
  894. X                size *= 10;
  895. X                size += (*ap++ - '0');
  896. X            }
  897. X            if (isdatum)
  898. X                sizp->size = size;    /* Datum size        */
  899. X            else
  900. X                sizp->psize = size; /* Pointer size     */
  901. X            sizp++;
  902. X            }
  903. X            if (sizp->bits != endtest)
  904. X            cwarn("-S, too few values specified in %s", argv[i]);
  905. X            else if (*ap != EOS)
  906. X            cwarn("-S, too many values, \"%s\" unused", ap);
  907. X            break;
  908. X#endif /* OK_SIZEOF */
  909. X
  910. X        case 'U':                       /* Undefine symbol      */
  911. X#if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
  912. X            zap_uc(ap);
  913. X#endif
  914. X            if (defendel(ap, TRUE) == NULL)
  915. X            cwarn("\"%s\" wasn't defined", ap);
  916. X            break;
  917. X        case 'W':
  918. X            wflag++;
  919. X            break;
  920. X#if DEBUG
  921. X        case 'X':                       /* Debug                */
  922. X            debug = (isdigit(*ap)) ? atoi(ap) : 1;
  923. X#if (HOST == SYS_VMS || HOST == SYS_UNIX)
  924. X            signal(SIGINT, abort);      /* Trap "interrupt"     */
  925. X#endif
  926. X            fprintf(stderr, "Debug set to %d\n", debug);
  927. X            break;
  928. X#endif
  929. X
  930. X        default:            /* What is this one?    */
  931. X            cwarn("Unknown option \"%s\"", arg);
  932. Xfprintf(stderr, "The following options are valid:\n");
  933. Xfprintf(stderr, "  -C\t\t\tWrite source file comments to output\n");
  934. Xfprintf(stderr, "  -Dsymbol=value");
  935. Xfprintf(stderr, "\tDefine a symbol with the given (optional) value\n");
  936. Xfprintf(stderr, "  -Idirectory");
  937. Xfprintf(stderr, "\t\tAdd a directory to the #include search list\n");
  938. Xfprintf(stderr, "  -N\t\t\tDon't predefine target-specific names\n");
  939. Xfprintf(stderr, "  -Stext\t\tSpecify sizes for #if sizeof\n");
  940. Xfprintf(stderr, "  -Usymbol\t\tUndefine symbol\n");
  941. X#if DEBUG
  942. X            fprintf(stderr, "  -Xvalue\t\tSet internal debug flag\n");
  943. X#endif
  944. X            break;
  945. X        }            /* Switch on all options    */
  946. X        }                /* If it's a -option            */
  947. X    }                /* For all arguments        */
  948. X    if (j > 3) {
  949. X        cerror(
  950. X        "Too many file arguments.  Usage: cpp [input [output]]",
  951. X        NULLST);
  952. X    }
  953. X    DBUG_RETURN (j);                        /* Return new argc              */
  954. X}
  955. X
  956. X#if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
  957. XFILE_LOCAL
  958. Xzap_uc(ap)
  959. Xregister char    *ap;
  960. X/*
  961. X * Dec operating systems mangle upper-lower case in command lines.
  962. X * This routine forces the -D and -U arguments to uppercase.
  963. X * It is called only on cpp startup by dooptions().
  964. X */
  965. X{
  966. X    DBUG_ENTER ("zap_uc");
  967. X    while (*ap != EOS) {
  968. X        /*
  969. X         * Don't use islower() here so it works with Multinational
  970. X         */
  971. X        if (*ap >= 'a' && *ap <= 'z')
  972. X        *ap = toupper(*ap);
  973. X        ap++;
  974. X    }
  975. X    DBUG_VOID_RETURN;
  976. X}
  977. X#endif
  978. X
  979. Xinitdefines()
  980. X/*
  981. X * Initialize the built-in #define's.  There are two flavors:
  982. X *    #define decus    1        (static definitions)
  983. X *    #define __FILE__ ??        (dynamic, evaluated by magic)
  984. X * Called only on cpp startup.
  985. X *
  986. X * Note: the built-in static definitions are supressed by the -N option.
  987. X * __LINE__, __FILE__, __TIME__ and __DATE__ are always present.
  988. X */
  989. X{
  990. X    register char        **pp;
  991. X    register char        *tp;
  992. X    register DEFBUF     *dp;
  993. X    register struct tm    *tm, *localtime();
  994. X    int            i;
  995. X    long            tvec;
  996. X
  997. X    static char months[12][4] = {
  998. X        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  999. X        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  1000. X    };
  1001. X
  1002. X    DBUG_ENTER ("initdefines");
  1003. X    DBUG_2 ("defs", "initialize built in defines");
  1004. X    /*
  1005. X     * Predefine the built-in symbols.  Allow the
  1006. X     * implementor to pre-define a symbol as "" to
  1007. X     * eliminate it.
  1008. X     */
  1009. X    if (nflag == 0) {
  1010. X        for (pp = preset; *pp != NULL; pp++) {
  1011. X        if (*pp[0] != EOS) {
  1012. X            dp = defendel(*pp, FALSE);
  1013. X            dp->repl = savestring("1");
  1014. X            dp->nargs = DEF_NOARGS;
  1015. X        }
  1016. X        }
  1017. X    }
  1018. X    /*
  1019. X     * The magic pre-defines (__FILE__ and __LINE__ are
  1020. X     * initialized with negative argument counts.  expand()
  1021. X     * notices this and calls the appropriate routine.
  1022. X     * DEF_NOARGS is one greater than the first "magic" definition.
  1023. X     */
  1024. X    if (nflag < 2) {
  1025. X        for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
  1026. X        dp = defendel(*pp, FALSE);
  1027. X        dp->nargs = --i;
  1028. X        }
  1029. X#if OK_DATE
  1030. X        /*
  1031. X         * Define __DATE__ as today's date.
  1032. X         */
  1033. X        dp = defendel("__DATE__", FALSE);
  1034. X        dp->repl = tp = getmem(14);
  1035. X        dp->nargs = DEF_NOARGS;
  1036. X        time(&tvec);
  1037. X        tm = localtime(&tvec);
  1038. X        sprintf(tp, "\"%3s %2d %4d\"",      /* "Aug 20 1988" */
  1039. X        months[tm->tm_mon],
  1040. X        tm->tm_mday,
  1041. X        tm->tm_year + 1900);
  1042. X
  1043. X        /*
  1044. X         * Define __TIME__ as this moment's time.
  1045. X         */
  1046. X        dp = defendel("__TIME__", FALSE);
  1047. X        dp->repl = tp = getmem(11);
  1048. X        dp->nargs = DEF_NOARGS;
  1049. X        sprintf(tp, "\"%2d:%02d:%02d\"",    /* "20:42:31" */
  1050. X        tm->tm_hour,
  1051. X        tm->tm_min,
  1052. X        tm->tm_sec);
  1053. X#endif
  1054. X    }
  1055. X    DBUG_VOID_RETURN;
  1056. X}
  1057. X
  1058. Xdeldefines()
  1059. X/*
  1060. X * Delete the built-in #define's.
  1061. X */
  1062. X{
  1063. X    register char        **pp;
  1064. X    int            i;
  1065. X
  1066. X
  1067. X    DBUG_ENTER ("deldefines");
  1068. X    DBUG_2 ("deldefs", "delete built in defines");
  1069. X    /*
  1070. X     * Delete the built-in symbols, unless -WW.
  1071. X     */
  1072. X    if (wflag < 2) {
  1073. X        for (pp = preset; *pp != NULL; pp++) {
  1074. X        defendel(*pp, TRUE);
  1075. X        }
  1076. X    }
  1077. X    /*
  1078. X     * The magic pre-defines __FILE__ and __LINE__
  1079. X     */
  1080. X    for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
  1081. X        defendel(*pp, TRUE);
  1082. X    }
  1083. X#if OK_DATE
  1084. X    /*
  1085. X     * Undefine __DATE__.
  1086. X     */
  1087. X    defendel("__DATE__", TRUE);
  1088. X
  1089. X    /*
  1090. X     * Undefine __TIME__.
  1091. X     */
  1092. X    defendel("__TIME__", TRUE);
  1093. X#endif
  1094. X    DBUG_VOID_RETURN;
  1095. X}
  1096. X
  1097. X#if HOST == SYS_VMS
  1098. X/*
  1099. X * getredirection() is intended to aid in porting C programs
  1100. X * to VMS (Vax-11 C) which does not support '>' and '<'
  1101. X * I/O redirection.  With suitable modification, it may
  1102. X * useful for other portability problems as well.
  1103. X */
  1104. X
  1105. Xint
  1106. Xgetredirection(argc, argv)
  1107. Xint        argc;
  1108. Xchar        **argv;
  1109. X/*
  1110. X * Process vms redirection arg's.  Exit if any error is seen.
  1111. X * If getredirection() processes an argument, it is erased
  1112. X * from the vector.  getredirection() returns a new argc value.
  1113. X *
  1114. X * Warning: do not try to simplify the code for vms.  The code
  1115. X * presupposes that getredirection() is called before any data is
  1116. X * read from stdin or written to stdout.
  1117. X *
  1118. X * Normal usage is as follows:
  1119. X *
  1120. X *    main(argc, argv)
  1121. X *    int        argc;
  1122. X *    char        *argv[];
  1123. X *    {
  1124. X *        argc = getredirection(argc, argv);
  1125. X *    }
  1126. X */
  1127. X{
  1128. X    register char        *ap;    /* Argument pointer    */
  1129. X    int            i;    /* argv[] index     */
  1130. X    int            j;    /* Output index     */
  1131. X    int            file;    /* File_descriptor    */
  1132. X    extern int        errno;    /* Last vms i/o error    */
  1133. X
  1134. X    DBUG_ENTER ("getredirection");
  1135. X    for (j = i = 1; i < argc; i++) {   /* Do all arguments  */
  1136. X        switch (*(ap = argv[i])) {
  1137. X        case '<':                   /* <file                */
  1138. X        if (freopen(++ap, "r", stdin) == NULL) {
  1139. X            perror(ap);         /* Can't find file      */
  1140. X            exit(errno);        /* Is a fatal error     */
  1141. X        }
  1142. X        break;
  1143. X
  1144. X        case '>':                   /* >file or >>file      */
  1145. X        if (*++ap == '>') {     /* >>file               */
  1146. X            /*
  1147. X             * If the file exists, and is writable by us,
  1148. X             * call freopen to append to the file (using the
  1149. X             * file's current attributes).  Otherwise, create
  1150. X             * a new file with "vanilla" attributes as if the
  1151. X             * argument was given as ">filename".
  1152. X             * access(name, 2) returns zero if we can write on
  1153. X             * the specified file.
  1154. X             */
  1155. X            if (access(++ap, 2) == 0) {
  1156. X            if (freopen(ap, "a", stdout) != NULL)
  1157. X                break;    /* Exit case statement    */
  1158. X            perror(ap);     /* Error, can't append  */
  1159. X            exit(errno);    /* After access test    */
  1160. X            }            /* If file accessable    */
  1161. X        }
  1162. X        /*
  1163. X         * On vms, we want to create the file using "standard"
  1164. X         * record attributes.  creat(...) creates the file
  1165. X         * using the caller's default protection mask and
  1166. X         * "variable length, implied carriage return"
  1167. X         * attributes. dup2() associates the file with stdout.
  1168. X         */
  1169. X        if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
  1170. X         || dup2(file, fileno(stdout)) == -1) {
  1171. X            perror(ap);         /* Can't create file    */
  1172. X            exit(errno);        /* is a fatal error     */
  1173. X        }            /* If '>' creation      */
  1174. X        break;            /* Exit case test    */
  1175. X
  1176. X        default:
  1177. X        argv[j++] = ap;     /* Not a redirector    */
  1178. X        break;            /* Exit case test    */
  1179. X        }
  1180. X    }                /* For all arguments    */
  1181. X    argv[j] = NULL;         /* Terminate argv[]    */
  1182. X    DBUG_RETURN (j);                /* Return new argc      */
  1183. X}
  1184. X#endif
  1185. X
  1186. X
  1187. END_OF_FILE
  1188. if test 14103 -ne `wc -c <'Cpp3.c'`; then
  1189.     echo shar: \"'Cpp3.c'\" unpacked with wrong size!
  1190. fi
  1191. # end of 'Cpp3.c'
  1192. fi
  1193. if test -f 'org/cpp.mem' -a "${1}" != "-c" ; then 
  1194.   echo shar: Will not clobber existing file \"'org/cpp.mem'\"
  1195. else
  1196. echo shar: Extracting \"'org/cpp.mem'\" \(12104 characters\)
  1197. sed "s/^X//" >'org/cpp.mem' <<'END_OF_FILE'
  1198. X
  1199. X
  1200. X
  1201. X
  1202. X        1.0  C Pre-Processor
  1203. X
  1204. X
  1205. X
  1206. X                                    *******
  1207. X                                    * cpp *
  1208. X                                    *******
  1209. X
  1210. X
  1211. X
  1212. X        NAME:   cpp -- C Pre-Processor
  1213. X
  1214. X        SYNOPSIS:
  1215. X
  1216. X                cpp [-options] [infile [outfile]]
  1217. X
  1218. X        DESCRIPTION:
  1219. X
  1220. X                CPP reads a C source file, expands  macros  and  include
  1221. X                files,  and writes an input file for the C compiler.  If
  1222. X                no file arguments are given, CPP reads  from  stdin  and
  1223. X                writes  to  stdout.   If  one file argument is given, it
  1224. X                will define the input file,  while  two  file  arguments
  1225. X                define  both  input and output files.  The file name "-"
  1226. X                is a synonym for stdin or stdout as appropriate.
  1227. X
  1228. X                The following options are  supported.   Options  may  be
  1229. X                given in either case.
  1230. X
  1231. X                -C              If set, source-file comments are written
  1232. X                                to  the  output  file.   This allows the
  1233. X                                output of CPP to be used as the input to
  1234. X                                a  program,  such  as lint, that expects
  1235. X                                commands embedded in specially-formatted
  1236. X                                comments.
  1237. X
  1238. X                -Dname=value    Define the name  as  if  the  programmer
  1239. X                                wrote
  1240. X
  1241. X                                    #define name value
  1242. X
  1243. X                                at the start  of  the  first  file.   If
  1244. X                                "=value"  is  not  given, a value of "1"
  1245. X                                will be used.
  1246. X
  1247. X                                On non-unix systems, all alphabetic text
  1248. X                                will be forced to upper-case.
  1249. X
  1250. X                -E              Always return "success" to the operating
  1251. X                                system,  even  if  errors were detected.
  1252. X                                Note that some fatal errors, such  as  a
  1253. X                                missing  #include  file,  will terminate
  1254. X                                CPP, returning "failure" even if the  -E
  1255. X                                option is given.
  1256. X                                                                          Page 2
  1257. X        cpp     C Pre-Processor
  1258. X
  1259. X
  1260. X                -Idirectory     Add  this  directory  to  the  list   of
  1261. X                                directories  searched for #include "..."
  1262. X                                and #include <...> commands.  Note  that
  1263. X                                there  is  no space between the "-I" and
  1264. X                                the directory string.  More than one  -I
  1265. X                                command   is   permitted.   On  non-Unix
  1266. X                                systems   "directory"   is   forced   to
  1267. X                                upper-case.
  1268. X
  1269. X                -N              CPP  normally  predefines  some  symbols
  1270. X                                defining   the   target   computer   and
  1271. X                                operating system.  If -N  is  specified,
  1272. X                                no symbols will be predefined.  If -N -N
  1273. X                                is  specified,  the   "always   present"
  1274. X                                symbols,    __LINE__,    __FILE__,   and
  1275. X                                __DATE__ are not defined.
  1276. X
  1277. X                -Stext          CPP normally assumes that  the  size  of
  1278. X                                the  target  computer's  basic  variable
  1279. X                                types is the same as the size  of  these
  1280. X                                types  of  the host computer.  (This can
  1281. X                                be  overridden  when  CPP  is  compiled,
  1282. X                                however.)  The  -S option allows dynamic
  1283. X                                respecification of these values.  "text"
  1284. X                                is  a  string  of  numbers, separated by
  1285. X                                commas, that  specifies  correct  sizes.
  1286. X                                The sizes must be specified in the exact
  1287. X                                order:
  1288. X
  1289. X                                    char short int long float double
  1290. X
  1291. X                                If you specify the option as  "-S*text",
  1292. X                                pointers   to   these   types   will  be
  1293. X                                specified.   -S*  takes  one  additional
  1294. X                                argument  for  pointer to function (e.g.
  1295. X                                int (*)())
  1296. X
  1297. X                                For   example,    to    specify    sizes
  1298. X                                appropriate  for  a  PDP-11,  you  would
  1299. X                                write:
  1300. X
  1301. X                                       c s i l f d func
  1302. X                                     -S1,2,2,2,4,8,
  1303. X                                    -S*2,2,2,2,2,2,2
  1304. X
  1305. X                                Note that all values must be specified.
  1306. X
  1307. X                -Uname          Undefine the name as if
  1308. X
  1309. X                                    #undef name
  1310. X
  1311. X                                were given.  On non-Unix systems, "name"
  1312. X                                will be forced to upper-case.
  1313. X                                                                          Page 3
  1314. X        cpp     C Pre-Processor
  1315. X
  1316. X
  1317. X                -Xnumber        Enable debugging code.  If no  value  is
  1318. X                                given,  a value of 1 will be used.  (For
  1319. X                                maintenence of CPP only.)
  1320. X
  1321. X
  1322. X        PRE-DEFINED VARIABLES:
  1323. X
  1324. X                When CPP begins processing, the following variables will
  1325. X                have been defined (unless the -N option is specified):
  1326. X
  1327. X                Target computer (as appropriate):
  1328. X
  1329. X                    pdp11, vax, M68000 m68000 m68k
  1330. X
  1331. X                Target operating system (as appropriate):
  1332. X
  1333. X                    rsx, rt11, vms, unix
  1334. X
  1335. X                Target compiler (as appropriate):
  1336. X
  1337. X                    decus, vax11c
  1338. X
  1339. X                The implementor may add definitions to this  list.   The
  1340. X                default  definitions  match  the  definition of the host
  1341. X                computer, operating system, and C compiler.
  1342. X
  1343. X                The following are always available unless undefined  (or
  1344. X                -N was specified twice):
  1345. X
  1346. X                    __FILE__    The  input  (or  #include)  file   being
  1347. X                                compiled (as a quoted string).
  1348. X
  1349. X                    __LINE__    The line number being compiled.
  1350. X
  1351. X                    __DATE__    The date and time of  compilation  as  a
  1352. X                                Unix  ctime  quoted string (the trailing
  1353. X                                newline is removed).  Thus,
  1354. X
  1355. X                                    printf("Bug at line %s,", __LINE__);
  1356. X                                    printf(" source file %s", __FILE__);
  1357. X                                    printf(" compiled on %s", __DATE__);
  1358. X
  1359. X
  1360. X        DRAFT PROPOSED ANSI STANDARD CONSIDERATIONS:
  1361. X
  1362. X                The current  version  of  the  Draft  Proposed  Standard
  1363. X                explicitly  states  that  "readers  are requested not to
  1364. X                specify or claim conformance to this draft." Readers and
  1365. X                users  of  Decus  CPP  should  not assume that Decus CPP
  1366. X                conforms to the standard, or that it will conform to the
  1367. X                actual C Language Standard.
  1368. X
  1369. X                When CPP is itself compiled, many features of the  Draft
  1370. X                Proposed  Standard  that  are incompatible with existing
  1371. X                                                                          Page 4
  1372. X        cpp     C Pre-Processor
  1373. X
  1374. X
  1375. X                preprocessors may be  disabled.   See  the  comments  in
  1376. X                CPP's source for details.
  1377. X
  1378. X                The latest version of the Draft  Proposed  Standard  (as
  1379. X                reflected in Decus CPP) is dated November 12, 1984.
  1380. X
  1381. X                Comments are removed from the input text.   The  comment
  1382. X                is  replaced by a single space character.  The -C option
  1383. X                preserves comments, writing them to the output file.
  1384. X
  1385. X                The '$' character is considered to be a letter.  This is
  1386. X                a permitted extension.
  1387. X
  1388. X                The following new features of C are processed by CPP:
  1389. X
  1390. X                    #elif expression (#else #if)
  1391. X                    '\xNNN' (Hexadecimal constant)
  1392. X                    '\a' (Ascii BELL)
  1393. X                    '\v' (Ascii Vertical Tab)
  1394. X                    #if defined NAME 1 if defined, 0 if not
  1395. X                    #if defined (NAME) 1 if defined, 0 if not
  1396. X                    #if sizeof (basic type)
  1397. X                    unary +
  1398. X                    123U, 123LU Unsigned ints and longs.
  1399. X                    12.3L Long double numbers
  1400. X                    token#token Token concatenation
  1401. X                    #include token Expands to filename
  1402. X
  1403. X                The Draft Proposed Standard has  extended  C,  adding  a
  1404. X                constant string concatenation operator, where
  1405. X
  1406. X                    "foo" "bar"
  1407. X
  1408. X                is regarded as the single string "foobar".   (This  does
  1409. X                not  affect  CPP's  processing but does permit a limited
  1410. X                form of macro argument substitution into strings as will
  1411. X                be discussed.)
  1412. X
  1413. X                The Standard Committee plans to add token  concatenation
  1414. X                to  #define command lines.  One suggested implementation
  1415. X                is as follows:  the sequence "Token1#Token2" is  treated
  1416. X                as  if  the programmer wrote "Token1Token2".  This could
  1417. X                be used as follows:
  1418. X
  1419. X                    #line 123
  1420. X                    #define ATLINE foo#__LINE__
  1421. X
  1422. X                ATLINE would be defined as foo123.
  1423. X
  1424. X                Note that "Token2" must either have  the  format  of  an
  1425. X                identifier or be a string of digits.  Thus, the string
  1426. X
  1427. X                    #define ATLINE foo#1x3
  1428. X                                                                          Page 5
  1429. X        cpp     C Pre-Processor
  1430. X
  1431. X
  1432. X                generates two tokens:  "foo1" and "x3".
  1433. X
  1434. X                If the tokens T1 and T2 are concatenated into  T3,  this
  1435. X                implementation operates as follows:
  1436. X
  1437. X                  1. Expand T1 if it is a macro.
  1438. X                  2. Expand T2 if it is a macro.
  1439. X                  3. Join the tokens, forming T3.
  1440. X                  4. Expand T3 if it is a macro.
  1441. X
  1442. X                A macro formal parameter  will  be  substituted  into  a
  1443. X                string or character constant if it is the only component
  1444. X                of that constant:
  1445. X
  1446. X                    #define VECSIZE 123
  1447. X                    #define vprint(name, size) \
  1448. X                      printf("name" "[" "size" "] = {\n")
  1449. X                      ... vprint(vector, VECSIZE);
  1450. X
  1451. X                expands (effectively) to
  1452. X
  1453. X                      vprint("vector[123] = {\n");
  1454. X
  1455. X                Note that  this  will  be  useful  if  your  C  compiler
  1456. X                supports  the  new  string concatenation operation noted
  1457. X                above.  As implemented here, if you write
  1458. X
  1459. X                    #define string(arg) "arg"
  1460. X                      ... string("foo") ...
  1461. X
  1462. X                This implementation generates  "foo",  rather  than  the
  1463. X                strictly  correct  ""foo"" (which will probably generate
  1464. X                an error message).  This is, strictly speaking, an error
  1465. X                in CPP and may be removed from future releases.
  1466. X
  1467. X        ERROR MESSAGES:
  1468. X
  1469. X                Many.  CPP prints warning or error messages if  you  try
  1470. X                to     use     multiple-byte     character     constants
  1471. X                (non-transportable) if you #undef a symbol that was  not
  1472. X                defined,  or  if  your  program  has  potentially nested
  1473. X                comments.
  1474. X
  1475. X        AUTHOR:
  1476. X
  1477. X                Martin Minow
  1478. X
  1479. X        BUGS:
  1480. X
  1481. X                The #if expression processor uses signed integers  only.
  1482. X                I.e, #if 0xFFFFu < 0 may be TRUE.
  1483. X
  1484. END_OF_FILE
  1485. if test 12104 -ne `wc -c <'org/cpp.mem'`; then
  1486.     echo shar: \"'org/cpp.mem'\" unpacked with wrong size!
  1487. fi
  1488. # end of 'org/cpp.mem'
  1489. fi
  1490. echo shar: End of archive 2 \(of 5\).
  1491. cp /dev/null ark2isdone
  1492. MISSING=""
  1493. for I in 1 2 3 4 5 ; do
  1494.     if test ! -f ark${I}isdone ; then
  1495.     MISSING="${MISSING} ${I}"
  1496.     fi
  1497. done
  1498. if test "${MISSING}" = "" ; then
  1499.     echo You have unpacked all 5 archives.
  1500.     rm -f ark[1-9]isdone
  1501. else
  1502.     echo You still need to unpack the following archives:
  1503.     echo "        " ${MISSING}
  1504. fi
  1505. ##  End of shell archive.
  1506. exit 0
  1507. -- 
  1508. Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
  1509.     amiga@cs.odu.edu    
  1510. or    amiga@xanth.cs.odu.edu    ( obsolescent mailers may need this address )
  1511. or    ...!uunet!xanth!amiga    ( very obsolescent mailers need this address )
  1512.  
  1513. Comments, questions, and suggestions s should be addressed to ``amiga-request''
  1514. (only use ``amiga'' for submissions) at the above addresses.
  1515.